package dbservice

import (
	"fmt"
	"math"
	"strconv"
	"strings"
	"time"

	"src/zeus/common"
	"src/zeus/logger"
	log "src/zeus/logger"
)

/*
账号数据
目前用来做假充值的逻辑
*/
type accountUtil struct {
	uid uint64
}

const (

	// AccountPrefix 帐号表前缀
	AccountPrefix = "account"

	// AccountOpenID 用户名表前缀, 存储帐号和UID的对应关系
	AccountOpenID = "accountopenid"

	// UIDField UID字段
	UIDField = "uid"
	//防沉迷 月充值数据
	SessionInfo_ageMonthPay = "ageMonthPay"
)

// GetUID 通过username获取uid
func GetUID(user string) (uint64, error) {
	c := GetLoginRedis()
	defer c.Close()
	return c.HGet(c.Ctx, AccountOpenID+":"+user, UIDField).Uint64()
	// return redis.Uint64(c.Do("HGET", AccountOpenID+":"+user, UIDField))
}

// Account 获取帐号表工具类
func Account(uid uint64) *accountUtil {
	acc := &accountUtil{
		uid: uid,
	}
	return acc
}

// SetPassword 密码保存至redis
func (util *accountUtil) SetPassword(password string) error {
	return util.setValue("password", password)
}

// VerifyPassword 验证密码
func (util *accountUtil) VerifyPassword(password string) bool {
	pwd, err := util.getPassword()
	if err != nil {
		log.Error("Get password failed", err)
		return false
	}

	if pwd != password {
		log.Error("Password not match")
		return false
	}

	return true
}

// SetUsername 保存用户名
func (util *accountUtil) SetUsername(user string) error {
	c := GetLoginRedis()
	defer c.Close()

	// if reply, err := common.NewString(c.Do("HSETNX", util.key(), "username", user)); err != nil {
	// 	return err
	// } else if reply == 0 {
	// 	return fmt.Errorf("Account existed %s", user)
	// }
	if reply, err := c.HSetNX(c.Ctx, util.key(), "username", user).Result(); err != nil {
		return err
	} else if !reply {
		return fmt.Errorf("Account existed %s", user)
	}
	// _, err := c.Do("HSET", AccountOpenID+":"+user, UIDField, util.uid)
	err := c.HSet(c.Ctx, util.key(), UIDField, util.uid).Err()
	return err
}

// GetUsername 获得用户名
func (util *accountUtil) GetUsername() (string, error) {
	return util.getValue("username")
}

// SetGrade 设置帐号级别 1表示内部 2表示外部玩家
func (util *accountUtil) SetGrade(grade uint32) error {
	return util.setValue("grade", grade)
}

// GetGrade 获取帐号级别
func (util *accountUtil) GetGrade() (uint32, error) {
	v, err := util.getValue("grade")
	if err != nil {
		return math.MaxUint32, err
	}
	if v == "" {
		return 0, nil
	}
	grade, err := common.NewString(v).ToUint64()
	if err != nil {
		return math.MaxUint32, err
	}
	return uint32(grade), nil
}

// getPassword 方法根据用户名返回密码
func (util *accountUtil) getPassword() (string, error) {
	return util.getValue("password")
}

// setPlayerList
func (util *accountUtil) SetPlayerList(pid uint64) {

	pids, err := util.GetPlayerList()
	if err != nil {
		return
	}

	arrayNum := len(pids)
	pids = append(pids, pid)

	var strTotle string
	for i := range pids {
		string := strconv.FormatUint(pids[i], 10)
		if i == arrayNum {
			strTotle += string
		} else {
			strTotle += string + ","
		}
	}
	util.setValue("playerList", strTotle)
}

func (util *accountUtil) SetPlayerListForInit() {
	util.setValue("playerList", "")
}

// getPlayerList
func (util *accountUtil) GetPlayerList() ([]uint64, error) {
	strRedis, err := util.getValue("playerList")
	if err != nil {
		return nil, err
	}

	result := make([]uint64, 0)
	if strRedis != "" {
		ss := strings.Split(strRedis, ",")
		for _, d := range ss {
			pid, err := strconv.ParseUint(d, 10, 64)
			if err != nil {
				return nil, err
			}
			result = append(result, pid)
		}
	}

	return result, nil
}

func (util *accountUtil) IsAccountExist() bool {
	c := GetLoginRedis()
	defer c.Close()
	// r, err := c.Do("EXISTS", util.key())
	r, err := c.Exists(c.Ctx, util.key()).Result()
	if err != nil {
		log.Error(err)
		return false
	}
	return r != 0
	// v, err := redis.Bool(r, nil)
	// if err != nil {
	// 	log.Error(err)
	// 	return false
	// }
	// return v

}

func (util *accountUtil) getValue(field string) (string, error) {
	c := GetLoginRedis()
	defer c.Close()
	return c.HGet(c.Ctx, util.key(), field).Result()
	// return c.Do("HGET", util.key(), field)
}

func (util *accountUtil) setValue(field string, value interface{}) error {
	c := GetLoginRedis()
	defer c.Close()
	return c.HSet(c.Ctx, util.key(), field, value).Err()
	// _, err := c.Do("HSET", util.key(), field, value)
	// return err
}

func (util *accountUtil) key() string {
	return fmt.Sprintf("%s:%d", AccountPrefix, util.uid)
}

// 获取玩家 ageMonthPay
func (util *accountUtil) GetAgeMonthPay(checkDate bool) (int, error) {
	reply, err := util.getValue(SessionInfo_ageMonthPay)
	if err != nil {
		return 0, err
	}
	if checkDate {
		//上次的日期 对比是否是本月以内,如果不是则要重置
		oldTimeS, err := util.getValue(SessionInfo_ageMonthPay + "_time")
		if err != nil {
			return 0, err
		}
		oldTime, _ := common.NewString(oldTimeS).ToInt()
		if oldTime > 0 {
			y, m, _ := time.Unix(int64(oldTime), 0).Date()
			y2, m2, _ := time.Now().Date()
			//不是一个月的,则重置 月累计充值额度,并返回0元额度
			if y != y2 || m != m2 {
				_ = util.SetAgeMonthPay(0)
				return 0, nil
			}
		}
	}
	return common.NewString(reply).ToInt()
}
func (util *accountUtil) SetAgeMonthPay(v int) error {
	c := GetLoginRedis()
	defer c.Dispose()
	// if _, err := c.Hmset(util.key(), ageMonthPay, v); err != nil {
	// 	log.Error(err)
	// 	return err
	// }
	// if _, err := c.Hmset(util.key(), ageMonthPay+"_time", time.Now().Unix()); err != nil {
	// 	log.Error(err)
	// 	return err
	// }
	// return nil
	if err := c.HMSet(c.Ctx, util.key(), SessionInfo_ageMonthPay, v).Err(); err != nil {
		logger.Error(err)
		return err
	}
	if err := c.HMSet(c.Ctx, util.key(), SessionInfo_ageMonthPay+"_time", time.Now().Unix()).Err(); err != nil {
		logger.Error(err)
		return err
	}
	return nil
}

func (util *accountUtil) GetAgeMonthPayTime() int64 {
	//上次的日期 对比是否是本月以内,如果不是则要重置
	oldTimeS, err := util.getValue(SessionInfo_ageMonthPay + "_time")
	if err != nil {
		return 0
	}
	oldTime, _ := common.NewString(oldTimeS).ToInt64()
	return int64(oldTime)
}
func (util *accountUtil) SetAgeMonthPayTime(n int64) error {
	c := GetLoginRedis()
	defer c.Dispose()

	// if _, err := c.Hmset(util.key(), ageMonthPay+"_time", time.Now().Unix()); err != nil {
	// 	log.Error(err)
	// 	return err
	// }
	// return nil
	if err := c.HMSet(c.Ctx, util.key(), SessionInfo_ageMonthPay+"_time", time.Now().Unix()).Err(); err != nil {
		logger.Error(err)
		return err
	}
	return nil
}
